package com.guigu.tms.oms.service.impl;

import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.RandomUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.guigu.tms.commons.order.entity.*;
import com.guigu.tms.commons.order.entity.fact.AddressRule;
import com.guigu.tms.commons.order.entity.vo.Result;
import com.guigu.tms.oms.mapper.OrderCargoMapper;
import com.guigu.tms.oms.mapper.OrderMapper;
import com.guigu.tms.oms.mapper.TransportOrderMapper;
import com.guigu.tms.oms.service.*;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.guigu.tms.oms.util.BaiduMapUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;

import java.math.BigDecimal;
import java.text.DecimalFormat;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * <p>
 * 订单 服务实现类
 * </p>
 *
 * @author zwj
 * @since 2022-09-27
 */
@Service
public class OrderServiceImpl extends ServiceImpl<OrderMapper, Order> implements IOrderService {

    @Autowired
    private OrderMapper orderMapper;

    @Autowired
    private IOrderLocationService orderLocationService;

    @Autowired
    private IOrderCargoService orderCargoService;

    @Autowired
    private IRuleService ruleService;

    @Autowired
    private OrderCargoMapper orderCargoMapper;

    @Autowired
    private IGoodsTypeService goodsTypeService;

    @Autowired
    private IAgencyScopeService agencyScopeService;

    @Autowired
    private ICourierScopService courierScopService;

    @Autowired
    private ITaskPickupDispatchService pickupDispatchService;

    @Autowired
    private TransportOrderMapper transportOrderMapper;

    private final String PICKUP_VALIDATECODE="PICKUP_VALIDATECODE";

    @Autowired
    private StringRedisTemplate redisTemplate;

    @Autowired
    private SendService sendService;

    @Override
    public boolean createOrder(Order order) {
        String orderId=IdUtil.getSnowflake().nextIdStr();
        order.setOrderId(orderId);

        //获得寄件人和收件人地址坐标
        getFullAddress(order);
        String senderCoordinate = getCoordinate(order.getSenderFullAddress());
        String receiverCoordinate = getCoordinate(order.getReceiverFullAddress());

        //添加订单位置信息
        OrderLocation orderLocation = new OrderLocation();
        orderLocation.setOrderId(orderId);
        orderLocation.setSendLocation(senderCoordinate);
        orderLocation.setReceiveLocation(receiverCoordinate);
        orderLocation.setStatus("1");
        orderLocationService.addOrderLocation(orderLocation);

        //添加订单货品信息
        BigDecimal totalWeight = order.getOrderCargo().getTotalWeight();
        order.getOrderCargo().setOrderId(orderId);
        orderCargoService.addOrderCargo(order.getOrderCargo());


        //计算订单距离
        BigDecimal distance =getOrderdistance(senderCoordinate,receiverCoordinate);
        order.setDistance(distance);

        //计算订单金额
        AddressRule addressRule = new AddressRule();
        addressRule.setDistance(distance.doubleValue());
        addressRule.setTotalWeight(totalWeight.doubleValue());
        order.setAmount(ruleService.rule(addressRule));

        order.setPaymentStatus(1);
        order.setStatus(1);

        //获取订单所属机构
        order.setCurrentAgencyId(getOrderAgencyId(senderCoordinate));

        System.out.println(order);
        //生成快递员取件任务
        TaskPickupDispatch pickupDispatch = new TaskPickupDispatch();
        pickupDispatch.setId(IdUtil.getSnowflake().nextIdStr());
        pickupDispatch.setOrderId(orderId);
        pickupDispatch.setTaskType(1);
        pickupDispatch.setStatus(1);
        pickupDispatch.setAgencyId(order.getCurrentAgencyId());
        pickupDispatch.setCourierId(getCourierId(senderCoordinate));
        pickupDispatch.setEstimatedStartTime(order.getEstimatedArrivalTime().plusMinutes(-30));
        pickupDispatch.setEstimatedEndTime(order.getEstimatedArrivalTime().plusMinutes(30));
        if(StringUtils.isEmpty(pickupDispatch.getCourierId())){
            pickupDispatch.setAssignedStatus(3);
        }else{
            pickupDispatch.setAssignedStatus(2);
        }
        pickupDispatchService.save(pickupDispatch);

        //发送验证码给寄件人，用于快递员取件
        sendValidateCode(orderId,order.getSenderPhone());
        return orderMapper.insert(order)>0;
    }

    @Override
    public BigDecimal getOrderPrice(Order order) {

        //获得收发人地址全地址名
        getFullAddress(order);
        //获得收发件人地址坐标
        String senderCoordinate = getCoordinate(order.getSenderFullAddress());
        String receiverCoordinate = getCoordinate(order.getReceiverFullAddress());
        //计算订单距离
        BigDecimal orderDistance = getOrderdistance(receiverCoordinate, senderCoordinate);

        //计算订单价格
        AddressRule addressRule = new AddressRule();
        addressRule.setDistance(orderDistance.doubleValue());
        addressRule.setTotalWeight(order.getOrderCargo().getTotalWeight().doubleValue());
        BigDecimal orderPrice = ruleService.rule(addressRule);
        return orderPrice;
    }

    /**
     * 计算订单距离
     * @param senderAddressCoordinate 发件人地址坐标
     * @param receiverAddressCoordinate 收件人地址坐标
     * @return
     */
    public BigDecimal getOrderdistance(String senderAddressCoordinate,String receiverAddressCoordinate){
        //计算寄件地址和收件地址的距离
        Double distance = BaiduMapUtils.getDistance(senderAddressCoordinate, receiverAddressCoordinate);

        DecimalFormat decimalFormat = new DecimalFormat("#.##");
        String distanceStr = decimalFormat.format(distance/1000);
        return new BigDecimal(distanceStr);
    }

    //获得地址坐标
    public String getCoordinate(String address){
        return BaiduMapUtils.getCoordinate(address);
    }

    /**
     * 获得完整地址（省市区+详细地址）
     * @param order
     */
    public void getFullAddress(Order order){
        StringBuffer senderAddress=new StringBuffer();
        senderAddress.append(order.getSenderProvinceId())
                .append(order.getSenderCityId())
                .append(order.getSenderCountyId())
                .append(order.getSenderAddress());
        StringBuffer receiverAddress=new StringBuffer();
        receiverAddress.append(order.getReceiverProvinceId())
                .append(order.getReceiverProvinceId())
                .append(order.getReceiverCityId())
                .append(order.getReceiverAddress());
        order.setSenderFullAddress(senderAddress.toString());
        order.setReceiverFullAddress(receiverAddress.toString());
    }

    /**
     * 获取订单所属机构
     * @param location
     * @return
     */
    public String getOrderAgencyId(String location){
        //获得区域编号
        Map map = BaiduMapUtils.getLocationByPosition(location);
        String adcode = (String) map.get("adcode");

        //通过区域编号获得区域所有网点
        QueryWrapper<AgencyScope> wrapper = new QueryWrapper<>();
        wrapper.eq("area_id",adcode);
        List<AgencyScope> agencyScopes=agencyScopeService.list(wrapper);
        //获得距离最近的网点
        return caculate(agencyScopes,location);
    }


    /**
     * 根据发货地址获取距离最近的快递员
     * @param location
     * @return
     */
    public String getCourierId(String location){
        //获得区域编号
        Map map = BaiduMapUtils.getLocationByPosition(location);
        String adcode = (String) map.get("adcode");
        //根据区域查询快递员
        QueryWrapper<CourierScop> wrapper=new QueryWrapper<>();
        wrapper.eq("area_id",adcode);
        List<CourierScop> courierScops = courierScopService.list(wrapper);
        //计算距离最近的快递员
        return calcuateCourier(location,courierScops);
    }

    /**
     * 计算距离目标地址最近的网点
     * @param agencyScopes 所有网点
     * @param location 目标位置
     * @return
     */
    private String caculate(List<AgencyScope> agencyScopes, String location) {
        System.out.println(agencyScopes);
        System.out.println(location);
        for (AgencyScope agencyScope : agencyScopes) {
                List<List<Map>> mutiPoints = agencyScope.getMutiPointList();
                if(ObjectUtils.isEmpty(mutiPoints)){
                    continue;
                }
                for (List<Map> list : mutiPoints) {
                    String[] originArray = location.split(",");
                    //判断某个点是否在指定区域范围内
                    boolean flag = BaiduMapUtils.isInScope(list, Double.parseDouble(originArray[0]), Double.parseDouble(originArray[1]));
                    if (flag) {
                        return agencyScope.getAgencyId();
                    }
                }
            }
            return null;
    }

    /**
     * 计算距离目标地址最近的快递员
     * @param location
     * @param courierScopeList
     * @return
     */
    private String calcuateCourier(String location, List<CourierScop> courierScopeList) {
            for (CourierScop courierScope : courierScopeList) {
                List<List<Map>> mutiPoints = courierScope.getMutiPointList();
                if(ObjectUtils.isEmpty(mutiPoints)){
                    continue;
                }
                for (List<Map> list : mutiPoints) {
                    String[] originArray = location.split(",");
                    boolean flag = BaiduMapUtils.isInScope(list, Double.parseDouble(originArray[0]), Double.parseDouble(originArray[1]));
                    if (flag) {
                        return courierScope.getUserId();
                    }
                }
            }
        return null;
    }


    @Override
    public Order getOrderByOrderId(String orderId) {
        QueryWrapper<Order> wrapper = new QueryWrapper<>();
        wrapper.eq("order_id",orderId);
        Order order = orderMapper.selectOne(wrapper);

        //根据订单编号查询订单位置信息
        order.setOrderLocation(orderLocationService.getOrderLocationByOrderId(orderId));
        //根据订单编号查询订单货物信息
        order.setOrderCargo(orderCargoService.getOrderCargoByOrderId(orderId));
        //查询取件信息
        pickupDispatchService.getTaskPickupDispatchByOrderId(orderId,1);

        return order;
    }

    @Override
    public List<Order> getOrdersByMemberId(String memberId) {
        QueryWrapper<Order> wrapper=new QueryWrapper<>();
        wrapper.eq("member_id",memberId);
        return orderMapper.selectList(wrapper);
    }

    @Override
    public List<Order> getOrdersByMobile(String mobile) {
        QueryWrapper<Order> wrapper=new QueryWrapper<>();
        wrapper.eq("receiver_phone",mobile);
        return orderMapper.selectList(wrapper);
    }

    @Override
    public Result updateOrder(String orderId, Order orderDTO) {

        //根据订单编号查询订单
        Order order = getOrderByOrderId(orderId);

        //判断订单是否已取件或已到达网点
        Integer orderStatus=order.getStatus();
        if(orderStatus!=1){
            return Result.error(0,"sorry! 该订单已被取件无法修改！");
        }

        order.setSenderName(orderDTO.getSenderName());
        order.setSenderPhone(orderDTO.getSenderPhone());
        order.setSenderProvinceId(orderDTO.getSenderProvinceId());
        order.setSenderCityId(orderDTO.getSenderCityId());
        order.setSenderCountyId(orderDTO.getSenderCountyId());
        order.setSenderAddress(order.getSenderAddress());
        order.setReceiverName(orderDTO.getReceiverName());
        order.setReceiverPhone(orderDTO.getReceiverPhone());
        order.setReceiverProvinceId(orderDTO.getReceiverProvinceId());
        order.setReceiverCityId(orderDTO.getReceiverCityId());
        order.setReceiverCountyId(orderDTO.getReceiverCountyId());
        order.setReceiverAddress(orderDTO.getReceiverAddress());
        order.setSenderAddress(orderDTO.getSenderAddress());
        order.setPaymentMethod(orderDTO.getPaymentMethod());

        System.out.println(orderDTO.getOrderCargo());
        //修改货物信息
        orderCargoService.updateById(orderDTO.getOrderCargo());

        //重新计算订单距离
        getFullAddress(order);
        String senderCoordinate = getCoordinate(order.getSenderFullAddress());
        String receiverCoordinate = getCoordinate(order.getReceiverFullAddress());
        BigDecimal orderDistance = getOrderdistance(receiverCoordinate, senderCoordinate);
        order.setDistance(orderDistance);

        //重新计算订单价格
        BigDecimal orderPrice = getOrderPrice(orderDTO);
        order.setAmount(orderPrice);


        //重新计算订单所属网点
        order.setCurrentAgencyId(getOrderAgencyId(senderCoordinate));
        //修改订单位置信息
        QueryWrapper<OrderLocation> wrapper=new QueryWrapper<>();
        wrapper.eq("order_id",orderId);
        OrderLocation orderLocation = orderLocationService.getOne(wrapper);
        orderLocation.setSendLocation(senderCoordinate);
        orderLocation.setReceiveLocation(senderCoordinate);
        orderLocationService.updateById(orderLocation);

        //重新分配快递员
        String courierId = getCourierId(senderCoordinate);

        QueryWrapper<TaskPickupDispatch> wrapper1=new QueryWrapper<>();
        wrapper1.eq("order_id",orderId);
        TaskPickupDispatch pickupDispatch = pickupDispatchService.getOne(wrapper1);
        pickupDispatch.setAgencyId(order.getCurrentAgencyId());
        pickupDispatch.setCourierId(courierId);

        orderMapper.updateById(order);

        return Result.ok("订单修改成功！");
    }

    @Override
    public Result cancelOrder(String orderId,String cases) {
        //根据订单编号修改订单状态 （取消）
        orderMapper.updateOrderStatus(orderId,10);

        //根据订单编号删除订单位置信息
        HashMap<String, Object> map = new HashMap<>();
        map.put("order_id",orderId);
        orderLocationService.removeByMap(map);

        //根据订单编号查询快递作业信息
        QueryWrapper<TaskPickupDispatch> wrapper=new QueryWrapper<>();
        wrapper.eq("order_id", orderId);
        TaskPickupDispatch pickupDispatch = pickupDispatchService.getOne(wrapper);
        //修改快递作业单
        if(!ObjectUtils.isEmpty(pickupDispatch)){
            pickupDispatch.setStatus(2);
            pickupDispatch.setCancelTime(LocalDateTime.now());
            pickupDispatch.setMark(cases);
            pickupDispatchService.updateById(pickupDispatch);
        }
        return Result.ok();
    }

    public void sendValidateCode(String orderId,String phone){
        String key=PICKUP_VALIDATECODE+orderId;
        //生成验证码
        String code = RandomUtil.randomNumbers(4);
        //发送验证码
        String msg="【短信宝】您的验证码是"+code+",30秒内有效";
        String res=sendService.sendSms("wkj333","77ca3217e5694aa98b230b81a4e03c85",phone,msg);
        //将验证码放入redis缓存中
        redisTemplate.opsForValue().set(key,code);
    }


}
